#include "stdafx.h"
#include "gw_font.h"

#include "..\core\gw_game.h"

#include "..\core\gw_eventsList.h"

#include "../rendering/gw_mesh.h"

#include "..\math\gw_calc.h"
#include "..\math\gw_physicssystem.h"

Font::Font(void)
{
}

Font::~Font(void)
{ 
}

void Font::Initialize()
{
	m_factory.Initialize(5);
}

void Font::Shutdown()
{
	m_factory.Shutdown(); 

	if (m_renderQuad.GetMesh() != NULL) 
		delete m_renderQuad.GetMesh(); 
}

void Font::LoadFont(const char *_szTable, uint _texWidth, uint _texHeight, float _cellsize, float _kerning)
{
	float width = calc::Lerp(0, (float)_texWidth, _cellsize);
	float height = calc::Lerp(0, (float)_texHeight, _cellsize);
	
	m_width = width;
	m_height = height;
	m_startChar = 0;
	m_numRows = 16;
	m_numCols = 8;
	m_kerning = _kerning;

	m_renderQuad.SetRenderState(RS_DEFAULT_MODE, RS_DRAW_MESH);
	m_renderQuad.SetRenderState(RS_LIGHTING_MODE, RS_LIGHTING_DISABLED);
	m_renderQuad.SetRenderState(RS_OVERRIDE_MODE, RS_OVERRIDE_DRAW);
	m_renderQuad.SetRenderState(RS_TEXTURES, RS_TEXTURE0_ENABLED);
	m_renderQuad.SetRenderState(RS_TRANSPARENCY_MODE, RS_TRANSPARENCY_ENABLED);
	m_renderQuad.SetOverrideFunc(Render);
	m_renderQuad.SetExtraData((long long)this);
	m_renderQuad.SetColorData(Vector4(0,0,1,1));

	char buffer[256];
	sprintf_s(buffer, 256, "assets/Game/Resources/Fonts/%s", _szTable);
	std::string fullpath(buffer);

	m_renderQuad.LoadTexture(fullpath);

	Mesh *mesh = new Mesh;
	mesh->m_Verts.resize(4);
	mesh->m_Verts[0] = Vector3(0,0,0);
	mesh->m_Verts[1] = Vector3(1,0,0);
	mesh->m_Verts[2] = Vector3(1,1,0);
	mesh->m_Verts[3] = Vector3(0,1,0);

	mesh->m_Indicies.resize(6);
	mesh->m_Indicies[0] = 0;
	mesh->m_Indicies[1] = 1;
	mesh->m_Indicies[2] = 2;
	mesh->m_Indicies[3] = 0;
	mesh->m_Indicies[4] = 2;
	mesh->m_Indicies[5] = 3;

	mesh->m_Norms.resize(4);
	for(unsigned c = 0; c < 4; c++)
		mesh->m_Norms[c] = Vector3(0,0,1);

	mesh->m_UVs.resize(4);

	m_renderQuad.SetMesh(mesh);

}

void Font::RenderLetter(uint _row, uint _col, float _x, float _y, float _scale)
{
	float wScale = (m_width*_scale);
	float hScale = m_height*_scale;

	//make a copy of default quad
	Matrix tran = m_renderQuad.GetWorldMatrix();

	//make it letter sized
	calc::matrixScale(tran, Vector3(wScale, hScale, 1.f));

	//move into position
	tran.pos.x = _x;
	tran.pos.y = _y;

	Mesh * mesh = (Mesh*)m_renderQuad.GetMesh();

	mesh->m_UVs.resize(4);
	mesh->m_UVs[0].u = m_width*_row;
	mesh->m_UVs[0].v = m_height*(_col+1);
	mesh->m_UVs[1].u = m_width*(_row+1);
	mesh->m_UVs[1].v = m_height*(_col+1);
	mesh->m_UVs[2].u = m_width*(_row+1);
	mesh->m_UVs[2].v = m_height*_col;
	mesh->m_UVs[3].u = m_width*_row;
	mesh->m_UVs[3].v = m_height*_col;

	m_pRenderer->Render(mesh, tran);
}

RenderNode& Font::MakeString(const char *_szText, float _x, float _y, Vector4 _color, float _scale, bool _persistent, float _kerning)
{
	StringToDraw * todraw = m_factory.GetItem();

	todraw->m_text = std::string(_szText);
	todraw->m_scale = _scale;
	todraw->m_persistent = _persistent;
	todraw->m_isOrtho = true;

	if (_kerning < 0.0f)
		if (m_kerning > 0.0f && m_kerning <= 1.0f) 
			todraw->m_kerning = m_kerning;
		else
			todraw->m_kerning = 1.0f;

	todraw->m_collisionRect.bottom = _y;
	todraw->m_collisionRect.left = _x;
	todraw->m_collisionRect.top = _y + (m_height*_scale);
	todraw->m_collisionRect.right = _x + ((m_width*_scale)*strlen(_szText));
	
	Matrix trans = m_renderQuad.GetWorldMatrix();
	trans.pos.x = _x;
	trans.pos.y = _y;
	m_renderQuad.SetWorldMatrix(trans);
	m_renderQuad.SetColorData(_color);

	m_renderQuad.SetOverrideParam(todraw);

	return m_renderQuad;
}


RenderNode& Font::Make3dString( const char *_szText, Vector3 _pos, Vector4 _color, float _scale, bool _persistent)
{
	StringToDraw * todraw = m_factory.GetItem();

	todraw->m_text = std::string(_szText);
	todraw->m_scale = _scale;
	todraw->m_persistent = _persistent;
	todraw->m_isOrtho = false;
	
	Matrix trans = m_renderQuad.GetWorldMatrix();
	trans.pos = _pos;
	m_renderQuad.SetWorldMatrix(trans);
	m_renderQuad.SetColorData(_color);

	m_renderQuad.SetOverrideParam(todraw);

	return m_renderQuad;
}

// Override Function
void Font::Render(const RenderNode *_pRN, void *_pVoid)
{
	//do stuff here
	int val				= 0;
	Font * font			= ((Font*)_pRN->GetExtraData());
	StringToDraw * str	= (StringToDraw*)_pVoid;

	for (uint i = 0; i < str->m_text.size(); i++)
	{
		val = (int)str->m_text[i] - font->m_startChar;

		if (str->m_isOrtho)
		{
			font->RenderLetter( (val % font->m_numRows),									// column letter is in
								(val / font->m_numRows),									// row letter is in
								((_pRN->GetWorldMatrix().pos.x + (font->m_width*str->m_scale) * ((float)i*str->m_kerning))),// x pos
								(_pRN->GetWorldMatrix().pos.y),								// y pos
								str->m_scale);		
		}
	}

	if(!(str->m_persistent))
		font->m_factory.ReturnItem(str);
}

bool Font::CheckPicking(RenderNode _rn)
{
	POINT			cursor;
	float			x, y;
	StringToDraw *	todraw = (StringToDraw*)_rn.GetOverrideParam();
	OrthoRect		rect = todraw->m_collisionRect;
	ViewportData	vp = Renderer::GetInstance()->GetViewportData();

	GetCursorPos(&cursor);
	ScreenToClient(Game::GetInstance()->GetHwnd(), &cursor);
	cursor.y = vp.viewport[3] - cursor.y;

	x = calc::Lerp(0, (float)vp.screenWidth, (float)cursor.x);
	y = calc::Lerp(0, (float)vp.screenHeight, (float)cursor.y);

	if (rect.left < x && rect.right > x && rect.top > y && rect.bottom < y)
		return true;

	return false;
}